import * as Cesium from 'cesium'
import * as turf from '@turf/turf'
import config from '@/config/config.js'
import { saveAs } from 'file-saver'
import { MVTImageryProvider } from 'cesium-mvt-imagery-provider'
import DrawUtil from '../drawUtil'
import ProfileAnalyse from '../profileAnalyse'
import InundationAnalyse from '../inundationAnalyse'
import FogEffect from '../fogEffect'
import MeasureDistance from '../measure/MeasureDistance'
import MeasureArea from '../measure/MeasureArea'
import MeasureHeight from '../measure/MeasureHeight'
import RadarMaterialProperty from '../material/RadarMaterialProperty'
import LightWallMaterialProperty from '../material/LightWallMaterialProperty'
import PolylineTrailMaterialProperty from '../material/PolylineTrailMaterialProperty'

const { tdtUrl, token, subdomains, accessToken } = config
Cesium.Ion.defaultAccessToken = accessToken
const prefix = import.meta.env.VITE_BASE_URL
export default class MapViewer extends Cesium.Viewer {
  original              // 初始摄像头范围
  terrain               // 地形
  earthAtNight          // 卷帘分析图层
  earthAtNightClip      // 卷帘分析 + 分割按钮图层
  slider                // 卷帘分析的分割按钮
  chinaLayer            // 中国省份图层
  viewerElement         // 鹰眼图添加位置元素   
  viewer1               // 鹰眼图第二个viewer
  syncViewer            // cesium渲染地球时触发的回调函数
  profile               // 剖面分析类
  drawUtil              // 点线面绘制类
  inundation            // 淹没分析类
  geometries = new Cesium.EntityCollection()   // 空间几何功能添加的实体数组
  xinxi                 // 添加空间几何属性表
  listener              // 添加空间几何属性表随地球移动的事件
  geometryHandler       // 添加空间几何的点击handler
  glbAirPort            // 添加飞机glb模型
  tileset               // 添加3D Tileset模型
  radiationPattern = new Cesium.EntityCollection()     // 添加辐射圈
  radarPattern          // 添加雷达图
  dynamicWalls          // 添加动态墙
  circularDiffusion     // 添加圆扩散
  firePartices          // 火粒子效果
  fireEntity            // 火焰实体
  fogParticles          // 添加雾粒子效果
  rainEffect            // 添加雨水粒子效果
  snowFlakeEffect       // 添加雪花粒子效果
  rainRender            // 添加雨水粒子效果
  snowRender            // 雪花粒子的更新函数
  flowingWater          // 添加流动的水效果
  measureDistance       // 添加测量距离类
  measureArea           // 添加测量面积类
  measureHeight         // 添加测量高程类
  osmBuildings          // 添加OSM建筑物
  flyLine = new Cesium.EntityCollection()             // 添加飞线
  constructor(domId, opt) {
    const basicConfig = {
      animation: false,   // 动画小组件
      baseLayerPicker: false,  // 底图组件，选择三维数字地球的底图
      fullscreenButton: false,  // 全屏组件
      vrButton: false,    // VR模式
      geocoder: false,    // 地理编码搜索组件
      homeButton: false,  // 首页，点击之后将视图跳转到默认视角
      infoBox: false,     // 信息框
      sceneModePicker: false,  // 场景模式，切换2D、3D和Columbus Views（CV）模式
      selectionIndicator: false,  // 是否显示选取指示器组件
      timeline: false,    // 时间轴
      navigationHelpButton: false,    // 帮助提示，如何操作数字地球
      navigationInstructionsInitiallyVisible: false,
      // mapProjection: new Cesium.WebMercatorProjection(),
      // imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
      //   url: new Cesium.Resource({
      //     url: `${tdtUrl}img_w/wmts?tk=${token}`
      //   }),
      //   layer: "img",
      //   style: "default",
      //   format: "tile",
      //   tileMatrixSetID: "w",
      //   show: true,
      //   // 要用于 URL 模板中占位符的子域。
      //   subdomains: subdomains,
      //   maximumLevel: 10
      // }),
      // 打印地图需要写上这个属性
      contextOptions: {
        requestWebgl1: true,
        webgl: {
          alpha: true,
          depth: true,
          stencil: true,
          antialias: true,
          premultipliedAlpha: true,
          preserveDrawingBuffer: true,
          failIfMajorPerformanceCaveat: false
        }
      },
      shouldAnimate: true
    }
    const extendConfig = {}
    super(domId, { ...basicConfig, ...extendConfig })
    this.original = opt.original
    this.scene.skyAtmosphere.show = false  // 关闭大气层
    this.scene.postProcessStages.fxaa.enabled = true // 设置抗锯齿
  }
  // 一、基础操作
  // 1，重置照相机到全球视角
  reset(duration = 1, boxArr) {
    const resultArr = boxArr || this.original
    this.camera.flyTo({
      destination: Cesium.Rectangle.fromDegrees(...resultArr),
      duration
    })
  }
  // 2，地图放大级别
  zoomIn() {
    const { height, longitude, latitude } = this.camera.positionCartographic
    if (height > 300000) {
      // 单位是米，沿相机的视图矢量进行缩放
      this.camera.zoomIn(300000)
    } else if (height > 1100 && height <= 300000) {
      this.camera.zoomIn(height / 2)
    } else {
      this.camera.flyTo({
        destination: Cesium.Cartesian3.fromRadians(longitude, latitude, 1100),
        duration: 1
      })
    }
  }
  // 3，地图缩小级别
  zoomOut() {
    const { height } = this.camera.positionCartographic
    if (height < 15772269) {
      this.camera.zoomOut(300000)
    }
  }
  // 4，二三维切换
  switchDimensional() {
    // this.scene.mode是2或者3，代表二维和三维
    this.scene.mode = 5 - this.scene.mode
  }
  // 5，导出地图
  exportMap() {
    const canvas = this.scene.canvas
    canvas.toBlob(blob => {
      saveAs(blob, 'map.png')
    })
  }
  // 6，更换为影像图
  toggleImageryLayer() {
    if (this.baseLayer) {
      this.scene.imageryLayers.remove(this.baseLayer)
    }
    this.baseLayer = this.scene.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
      url: 'http://t1.tianditu.com/img_w/wmts?layer=img&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=590447cdbdf97775b57588a69ebb903d'
    }))
  }
  // 7，更换为地形图
  toggleTerrainLayer() {
    if (this.baseLayer) {
      this.scene.imageryLayers.remove(this.baseLayer)
    }
    this.baseLayer = this.scene.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
      url: 'http://t1.tianditu.com/ter_w/wmts?layer=ter&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=590447cdbdf97775b57588a69ebb903d'
    }))
  }
  // 8，更换为矢量图
  toggleVectorLayer() {
    if (this.baseLayer) {
      this.scene.imageryLayers.remove(this.baseLayer)
    }
    this.baseLayer = this.scene.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
      url: 'http://t1.tianditu.com/vec_w/wmts?layer=vec&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=590447cdbdf97775b57588a69ebb903d'
    }))
  }
  // 9，地球自转
  enableEarthRotation() {
    let that = this
    let prev = Cesium.JulianDate.now(new Date())
    function xuanzhuan() {
      let currentTime = Cesium.JulianDate.now(new Date())
      if ((currentTime - prev) >= 5000) return
      // 通过旋转相机模拟地球自转的效果
      that.camera.rotate(Cesium.Cartesian3.UNIT_Z, -Math.PI * 0.1 / 180)
      requestAnimationFrame(xuanzhuan)
    }
    xuanzhuan()
  }
  // 10，开启雾天
  enableFoggyTurn() {
    if (this.scene.fog.enabled) {
      this.scene.fog.enabled = false
    } else {
      this.scene.fog.enabled = true  // 开启雾天
      this.scene.fog.minimumBrightness = 0.1   // 雾效果最小亮度
      this.scene.fog.density = 0.0003  // 浓度
    }
  }
  // 11，开启昼夜
  enableDayNightTurn() {
    if (this.scene.globe.enableLighting) {
      this.scene.globe.enableLighting = false
    } else {
      this.scene.globe.enableLighting = true  // 开启光照
    }
  }
  // 12，开启大气层(天空大气效果)
  enableAtmosphereTurn() {
    if (this.scene.skyAtmosphere.show) {
      this.scene.skyAtmosphere.show = false
    } else {
      this.scene.skyAtmosphere.show = true  // 开启天空大气效果
      this.scene.skyAtmosphere.atmosphereLightIntensity = 50  // 天空大气效果亮度
    }
  }
  // 13，开启地形
  async enableTerrainLoad() {
    if (!this.terrain) {
      try {
        this.terrain = new Cesium.CesiumTerrainProvider({
          url: Cesium.IonResource.fromAssetId(1),
          requestWaterMask: true,
          requestVertexNormals: true,
        })
        this.terrainProvider = this.terrain
        this.reset(1, [114, 31, 115, 32])
      } catch (error) {
        console.log(`Failed to add world imagery: ${error}`)
      }
    } else {
      this.terrain = null
      this.terrainProvider = new Cesium.EllipsoidTerrainProvider()
      this.reset()
    }
  }
  // 14，添加中国省份
  addChinaProvinces() {
    const layers = this.imageryLayers
    if (this.chinaLayer) {
      layers.remove(this.chinaLayer)
      this.chinaLayer = null
    } else {
      this.chinaLayer = layers.addImageryProvider(new MVTImageryProvider({
        urlTemplate: 'http://localhost:8082/geoserver/gwc/service/tms/1.0.0/workstation%3AZSYCity_Mercator@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf',
        layerName: 'ZSYCity_Mercator',
        credit: 'cesium.js',
        style: _feature => {
          return {
            strokeStyle: "green",
            fillStyle: "green",
            lineWidth: 1,
          }
        },
        onSelectFeature: _feature => {
          console.log("Feature is selected")
        },
      }))
    }
  }
  // 15，添加卷帘分析
  addRollerShutter(RollerShutterChecked) {
    const layers = this.imageryLayers
    if (this.earthAtNight && RollerShutterChecked) {
      layers.remove(this.earthAtNight)
      this.earthAtNight = null
    } else {
      this.earthAtNight = layers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
        url: 'http://t1.tianditu.com/vec_w/wmts?layer=vec&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=590447cdbdf97775b57588a69ebb903d'
      }))
      // 添加图层方向
      this.earthAtNight.splitDirection = Cesium.SplitDirection.LEFT
      // 添加图层分割位置
      this.scene.splitPosition = 0.5
    }
  }
  // 16，添加卷帘分析 + 分割按钮
  addRollerShutterClip(RollerShutterClipChecked) {
    const layers = this.imageryLayers
    let moveAction = false
    const move = (movement) => {
      if (!moveAction) return
      const relativeOffset = movement.endPosition.x
      const splitPosition = (this.slider.offsetLeft + relativeOffset) / this.slider.parentElement.offsetWidth
      this.slider.style.left = `${100.0 * splitPosition}%`
      // 改变图层分割位置
      this.scene.splitPosition = splitPosition
    }
    if (this.earthAtNightClip && this.slider && RollerShutterClipChecked) {
      layers.remove(this.earthAtNightClip)
      this.earthAtNightClip = null
      document.getElementsByClassName('cesium-main')[0].removeChild(this.slider)
      this.slider = null
    } else {
      this.earthAtNightClip = layers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
        url: 'http://t1.tianditu.com/vec_w/wmts?layer=vec&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=590447cdbdf97775b57588a69ebb903d'
      }))
      // 添加图层方向
      this.earthAtNightClip.splitDirection = Cesium.SplitDirection.LEFT
      // 添加图层分割位置
      this.scene.splitPosition = 0.5
      // 添加滑动控件slider
      this.slider = document.createElement('div')
      this.slider.style.width = 10 + 'px'
      this.slider.style.height = 50 + 'px'
      this.slider.style.position = 'absolute'
      this.slider.style.top = '50%'
      this.slider.style.left = '50%'
      this.slider.style.backgroundColor = 'brown'
      this.slider.style.cursor = 'pointer'
      document.getElementsByClassName('cesium-main')[0].appendChild(this.slider)
      const handler = new Cesium.ScreenSpaceEventHandler(this.slider)
      handler.setInputAction(() => {
        moveAction = true
      }, Cesium.ScreenSpaceEventType.LEFT_DOWN)
      handler.setInputAction(move, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
      handler.setInputAction(() => {
        moveAction = false
      }, Cesium.ScreenSpaceEventType.LEFT_UP)
    }

  }
  // 17，添加绘制工具
  addDrawUtil(type, div) {
    if (this.drawUtil) {
      this.drawUtil.removeDrawUtil()
      this.drawUtil = null
    } else {
      this.drawUtil = new DrawUtil(this, type, div)
      this.drawUtil.addDrawUtil()
    }
  }
  // 18，添加鹰眼图
  addOverView(overViewChecked, type) {
    const that = this
    if (overViewChecked) {
      // debugger
      that.canvas.parentElement.removeChild(that.viewerElement)
      that.viewer1 = null
      that.scene.preRender.removeEventListener(that.syncViewer)
      that.syncViewer = null
      that.viewerElement = null
    } else {
      if (that.viewerElement) {
        that.canvas.parentElement.removeChild(that.viewerElement)
        that.viewer1 = null
        that.scene.preRender.removeEventListener(that.syncViewer)
        that.syncViewer = null
        that.viewerElement = null
      }
      that.viewerElement = document.createElement('div')
      that.viewerElement.style.position = 'absolute'
      that.viewerElement.style.right = 0
      that.viewerElement.style.bottom = 0
      that.viewerElement.style.width = 300 + 'px'
      that.viewerElement.style.height = 150 + 'px'
      that.viewerElement.style.zIndex = 100
      that.canvas.parentElement.appendChild(that.viewerElement)
      that.viewer1 = new Cesium.Viewer(that.viewerElement, {
        animation: false,   // 动画小组件
        baseLayerPicker: false,  // 底图组件，选择三维数字地球的底图
        fullscreenButton: false,  // 全屏组件
        vrButton: false,    // VR模式
        geocoder: false,    // 地理编码搜索组件
        homeButton: false,  // 首页，点击之后将视图跳转到默认视角
        infoBox: false,     // 信息框
        sceneModePicker: false,  // 场景模式，切换2D、3D和Columbus Views（CV）模式
        selectionIndicator: false,  // 是否显示选取指示器组件
        timeline: false,    // 时间轴
        navigationHelpButton: false,    // 帮助提示，如何操作数字地球
        navigationInstructionsInitiallyVisible: false,
        mapProjection: new Cesium.WebMercatorProjection(),
        imageryProvider: new Cesium.UrlTemplateImageryProvider({
          url: 'http://t1.tianditu.com/img_w/wmts?layer=img&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=590447cdbdf97775b57588a69ebb903d'
        })
      })
      switch (type) {
        case '地形图':
          that.viewer1.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
            url: 'http://t1.tianditu.com/ter_w/wmts?layer=ter&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=590447cdbdf97775b57588a69ebb903d'
          }))
          break
        case '矢量图':
          that.viewer1.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
            url: 'http://t1.tianditu.com/vec_w/wmts?layer=vec&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=590447cdbdf97775b57588a69ebb903d'
          }))
          break
      }
      let control = that.viewer1.scene.screenSpaceCameraController
      // 禁止用户旋转世界
      control.enableRotate = false
      // 禁止用户平移
      control.enableTranslate = false
      // 禁止用户放大和缩小
      control.enableZoom = false
      // 禁止用户倾斜相机
      control.enableTilt = false
      // 禁止用户自由查看
      control.enableLook = false
      // cesium渲染地球时触发回调
      that.syncViewer = function (e) {
        // console.log(e)
        that.viewer1.camera.flyTo({
          // 目的地
          destination: that.camera.position,
          // 方向
          orientation: {
            heading: that.camera.heading,
            pitch: that.camera.pitch,
            roll: that.camera.roll
          },
          // 持续时间
          duration: 0.0
        })
      }
      that.scene.preRender.addEventListener(that.syncViewer)
    }
  }
  // 19，剖面分析
  addProfileAnalysis(profileAnalysisChecked, div) {
    if (profileAnalysisChecked && this.profile) {
      this.profile.removeProfileAnalysis()
      this.profile = null
    } else {
      this.profile = new ProfileAnalyse(this, div)
      this.profile.addProfileAnalysis()
    }
  }
  // 20，淹没分析
  addInundationAnalysis(inundationAnalysisChecked, div) {
    if (inundationAnalysisChecked && this.inundation) {
      this.inundation.removeInundationAnalysis()
      this.inundation = null
    } else {
      this.inundation = new InundationAnalyse(this, div)
      this.inundation.addInundationAnalysis()
    }
  }
  // 21，添加空间几何
  addGeometries(type) {
    let degrees1 = [100 + Math.floor(Math.random() * 20 + 1), 20 + Math.floor(Math.random() * 20 + 1)]
    let degrees2 = [100 + Math.floor(Math.random() * 20 + 1), 20 + Math.floor(Math.random() * 20 + 1)]
    let degrees3 = [100 + Math.floor(Math.random() * 20 + 1), 20 + Math.floor(Math.random() * 20 + 1)]
    switch (type) {
      case 'PicturePoint':
        let picturePoint = this.entities.add({
          position: Cesium.Cartesian3.fromDegrees(...degrees1),
          billboard: {
            // 图像地址，URI或Canvas的属性
            image: prefix + '/images/五角星.png',
            // 设置颜色和透明度
            color: Cesium.Color.WHITE.withAlpha(0.8),
            // 高度（以像素为单位）
            height: 50,
            // 宽度（以像素为单位）
            width: 50,
            // 逆时针旋转
            rotation: 20,
            // 大小是否以米为单位
            sizeInMeters: false,
            // 相对于坐标的垂直位置
            verticalOrigin: Cesium.VerticalOrigin.CENTER,
            // 相对于坐标的水平位置
            horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
            // 该属性指定标签在屏幕空间中距此标签原点的像素偏移量
            pixelOffset: new Cesium.Cartesian2(10, 0),
            // 应用于图像的统一比例。比例大于会1.0放大标签，而比例小于会1.0缩小标签。
            scale: 0.7,
            // 是否显示
            show: true
          }
        })
        this.geometries.add(picturePoint)
        this.geometryHandler = new Cesium.ScreenSpaceEventHandler(this.canvas)
        this.scene.globe.depthTestAgainstTerrain = true
        this.xinxi = document.createElement('div')
        let title = document.createElement('div')
        title.innerText = '点信息'
        title.style.textAlign = 'center'
        let close = document.createElement('span')
        close.innerText = 'x'
        close.style.position = 'absolute'
        close.style.top = 0
        close.style.right = 5 + 'px'
        close.style.cursor = 'pointer'
        close.addEventListener('click', () => this.xinxi.style.display = 'none')
        let ul = document.createElement('ul')
        ul.style.paddingLeft = 20 + 'px'
        this.xinxi.appendChild(title)
        this.xinxi.appendChild(close)
        this.xinxi.appendChild(ul)
        this.xinxi.style.width = 200 + 'px'
        this.xinxi.style.height = 100 + 'px'
        this.xinxi.style.borderRadius = 5 + 'px'
        this.xinxi.style.backgroundColor = '#fff'
        this.xinxi.style.zIndex = 100
        this.xinxi.style.position = 'absolute'
        this.xinxi.style.display = 'none'
        this.canvas.parentElement.appendChild(this.xinxi)
        this.geometryHandler.setInputAction((e) => {
          let aEntity = this.scene.pick(e.position)
          if (Cesium.defined(aEntity)) {
            let p1 = aEntity.id.position
            let a = Cesium.Cartographic.fromCartesian(p1._value)
            ul.insertAdjacentHTML('beforeend', `<li>经度：${Cesium.Math.toDegrees(a.longitude).toFixed(2)}</li>`)
            ul.insertAdjacentHTML('beforeend', `<li>纬度：${Cesium.Math.toDegrees(a.latitude).toFixed(2)}</li>`)
            this.xinxi.style.left = e.position.x + 50 + 'px'
            this.xinxi.style.top = e.position.y + 'px'
            this.xinxi.style.display = 'block'
            this.geometryHandler.destroy()
            this.geometryHandler = null
            this.listener = () => {
              let p2 = aEntity.id.position
              let canvasPosition = this.scene.cartesianToCanvasCoordinates(p2._value)
              this.xinxi.style.left = canvasPosition.x + 50 + 'px'
              this.xinxi.style.top = canvasPosition.y + 'px'
            }
            this.scene.postRender.addEventListener(this.listener)
          }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
        break
      case 'OriginalPoint':
        let originalPoint = this.entities.add({
          position: Cesium.Cartesian3.fromDegrees(...degrees1),
          point: {
            pixelSize: 20,   // 点像素大小
            color: Cesium.Color.YELLOW,
            outlineColor: Cesium.Color.RED
          }
        })
        this.geometries.add(originalPoint)
        break
      case 'FlowLine':
        let lineInstance = new Cesium.GeometryInstance({
          geometry: new Cesium.PolylineGeometry({
            positions: Cesium.Cartesian3.fromDegreesArray([
              120, 30,
              125, 32,
              128, 27
            ]),
            width: 5,
            vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT
          }),
          attributes: {
            color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.WHITE)
          }
        })
        let oneTypeLinesPrimitive = new Cesium.Primitive({
          geometryInstances: [lineInstance],
          appearance: new Cesium.PolylineMaterialAppearance({
            material: new Cesium.Material({
              fabric: {
                uniforms: {
                  image: prefix + '/images/图标点.png',
                  animationSpeed: 0.01
                },
                source: `czm_material czm_getMaterial(czm_materialInput materialInput) { 
                          czm_material material = czm_getDefaultMaterial(materialInput);
                          vec2 st = materialInput.st;
                          float time = czm_frameNumber * animationSpeed;
                          // 反复循环，使动画效果更加生动
                          time = abs(fract(time) - 0.5) * 2.0;
                          vec4 colorImage = texture2D(image,vec2(fract(st.s - time), st.t));
                          material.alpha = colorImage.a;
                          material.diffuse = colorImage.rgb;
                          return material;
                }`
              }
            })
          }),
          asynchronous: true
        })
        this.scene.primitives.add(oneTypeLinesPrimitive)
        break
      case 'ColorLine':
        let colorLine = this.entities.add({
          polyline: {
            positions: Cesium.Cartesian3.fromDegreesArray([
              ...degrees1,
              ...degrees2,
            ]),
            width: 5,
            material: Cesium.Color.fromRandom({
              maximumRed: 0.75,
              maximumGreen: 0.75,
              maximumBlue: 0.75,
              alpha: 1.0
            })
          }
        })
        this.geometries.add(colorLine)

        break
      case 'addPolygon':
        let polygon = this.entities.add({
          polygon: {
            // 等级制度，包括postions和holes两个属性
            hierarchy: {
              positions: Cesium.Cartesian3.fromDegreesArray([
                ...degrees1,
                ...degrees2,
                ...degrees3,
              ])
            },
            height: 0,  // 这个面所处的高度，不是这个面的高
            extrudedHeight: 1000,    // 这个面的高度
            material: Cesium.Color.fromRandom({
              maximumRed: 0.75,
              maximumGreen: 0.75,
              maximumBlue: 0.75,
              alpha: 1.0
            }).withAlpha(.5),  // withAlpha 其实就是opacity 透明度
            outline: true,
            fill: true,  // 是否填充颜色
            outlineColor: Cesium.Color.BLACK
          }
        })
        this.geometries.add(polygon)
        break
      case 'removeGeometries':
        if (this.geometries.values.length !== 0) {
          this.geometries.values.forEach(geometry => {
            this.entities.remove(geometry)
          })
          this.geometries.removeAll()
        } else {
          alert('没有添加几何，不能删除')
        }
        if (this.xinxi) {
          this.canvas.parentElement.removeChild(this.xinxi)
          this.xinxi = null
        }
        if (this.listener) {
          this.scene.postRender.removeEventListener(this.listener)
          this.listener = null
        }
        if (this.geometryHandler) {
          this.geometryHandler.destroy()
          this.geometryHandler = null
        }
        break
    }
  }
  // 22，添加3DTiles模型
  load3DTileSet(load3DTileSetChecked) {
    if (load3DTileSetChecked && this.tileset) {
      // 移除3dtileset数据源
      this.scene.primitives.remove(this.tileset)
      this.reset()
      this.tileset = null
    } else {
      this.tileset = new Cesium.Cesium3DTileset({
        url: prefix + '/Tileset/tileset.json',
        type: '3dtiles'
      })
      this.tileset.readyPromise.then(res => {
        // 1，添加TileSet
        this.scene.primitives.add(res)
        // 2，视图定位
        // HeadingPitchRange定义航向角、俯仰角和到中心点的距离
        this.zoomTo(res, new Cesium.HeadingPitchRange(
          0.0, -0.5, res.boundingSphere.radius * 2.0
        ))
        // this.flyTo(res)
        // 3，设置样式
        const properties = res.properties
        if (Cesium.defined(properties) && Cesium.defined(properties.Height)) {
          res.style = new Cesium.Cesium3DTileStyle({
            color: {
              conditions: [
                ["${Height} >= 83", "color('purple', 0.5)"],
                ["${Height} >= 80", "color('red')"],
                ["${Height} >= 70", "color('orange')"],
                ["${Height} >= 12", "color('yellow')"],
                ["${Height} >= 7", "color('lime')"],
                ["${Height} >= 1", "color('cyan')"],
                ["true", "color('blue')"]
              ]
            }
          })
        }
      })

    }
  }
  // 23，添加GLB模型
  loadgltfAir(loadgltfAirChecked) {
    if (loadgltfAirChecked && this.glbAirPort) {
      // 移除glb飞机数据源
      this.entities.remove(this.glbAirPort)
      this.reset()
      this.glbAirPort = null
    } else {
      const position = Cesium.Cartesian3.fromDegrees(
        120, 45
      )
      const heading = Cesium.Math.toRadians(0)
      const pitch = 0
      const roll = 0
      const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll)
      const orientation = Cesium.Transforms.headingPitchRollQuaternion(
        position,
        hpr
      )
      this.glbAirPort = this.entities.add({
        name: "Cesium_Air.glb",
        position: position,
        orientation: orientation,
        model: {
          uri: prefix + "/glb/Cesium_Air.glb",
          minimumPixelSize: 128,    // 最小像素大小
          maximumScale: 20000,   // 模型的最大比例尺大小
          scale: 1,   // 缩放比例
          incrementallyLoadTextures: true,   // 加载模型后的纹理是否可以继续流入
          runAnimations: true,     // 指定是否应运行 glTF 动画
          clampAnimations: true,    // 指定 glTF 动画是否应在不带关键帧的持续时间内保持最后一个姿势
          shadows: Cesium.ShadowMode.ENABLED,   // 指定模型是否 投射或接收来自光源的阴影
          heightReference: Cesium.HeightReference.NONE  // 表示相对于地形的位置。NONE表示绝对位置 
        }
      })
      this.trackedEntity = this.glbAirPort
    }
  }
  // 24，添加辐射圈
  addRadiationPattern(radiationPatternChecked) {
    if (radiationPatternChecked) {
      this.radiationPattern.values.forEach(entity => {
        this.entities.remove(entity)
      })
      this.radiationPattern.removeAll()
      this.reset()
    } else {
      for (let i = 0; i < 3; i++) {
        let minR1 = 4000, minR2 = 4000   // 最小半径
        let maxR1 = 400000, maxR2 = 400000  // 最大半径
        let deviationR1 = 2000, deviationR2 = 2000  // 每次增加的半径
        const changeR1 = () => {
          minR1 += deviationR1
          if (minR1 >= maxR1) {
            minR1 = 4000
          }
          return minR1
        }
        const changeR2 = () => {
          minR2 += deviationR2
          if (minR2 >= maxR2) {
            minR2 = 4000
          }
          return minR2
        }
        setTimeout(() => {
          this.radiationPattern.add(this.entities.add({
            position: Cesium.Cartesian3.fromDegrees(110, 40),
            ellipse: {
              semiMinorAxis: new Cesium.CallbackProperty(changeR1, false),
              semiMajorAxis: new Cesium.CallbackProperty(changeR2, false),
              outline: true,
              outlineColor: new Cesium.CallbackProperty(() => {
                let x = 1 - minR1 / maxR1
                return Cesium.Color.RED.withAlpha(x)
              }, false),
              material: new Cesium.ImageMaterialProperty({
                image: '/images/扩散圈.png',
                repeat: new Cesium.Cartesian2(1.0, 1.0),
                transparent: true,
                color: new Cesium.CallbackProperty(function () {
                  var alp = 1
                  alp = 1 - minR1 / maxR1
                  return Cesium.Color.WHITESMOKE.withAlpha(alp)
                }, false)
              })
            }
          }))
        }, i * 1000)
      }
    }
  }
  // 25，添加雷达图
  addRadarPattern(radarPatternChecked) {
    if (radarPatternChecked) {
      this.entities.remove(this.radarPattern)
      this.radarPattern = null
      this.reset()
    } else {
      this.radarPattern = this.entities.add({
        rectangle: {
          coordinates: Cesium.Rectangle.fromDegrees(
            110.97, 34.58, 116.37, 39.88),
          material: new RadarMaterialProperty('radarMaterial'),
        }
      })
    }
  }
  // 26，添加动态墙
  addDynamicWalls(dynamicWallsChecked) {
    if (dynamicWallsChecked) {
      this.entities.remove(this.dynamicWalls)
      this.dynamicWalls = null
      this.reset()
    } else {
      // let minHeight = 1000
      // let maxHeight = 100000
      // let deviationHeight = 1000
      this.dynamicWalls = this.entities.add({
        wall: {
          // maximumHeights: new Cesium.CallbackProperty(() => {
          //   minHeight += deviationHeight
          //   if (minHeight >= maxHeight) {
          //     minHeight = 1000
          //   }
          //   return [minHeight, minHeight, minHeight]
          // }, false),
          material: new LightWallMaterialProperty('lightWallMaterial'),
          positions: Cesium.Cartesian3.fromDegreesArrayHeights([
            115.0,
            34.0,
            200000.0,
            115.0,
            36.0,
            200000.0,
            118.0,
            36.0,
            200000.0
          ])
        }
      })
      this.zoomTo(this.dynamicWalls)
    }
  }
  // 27，添加圆扩散
  addCircularDiffusion(circularDiffusionChecked) {
    if (circularDiffusionChecked) {
      this.entities.remove(this.circularDiffusion)
      this.circularDiffusion = null
      this.reset()
    } else {
      let minR1 = 4000, minR2 = 4000   // 最小半径
      let maxR1 = 600000, maxR2 = 600000  // 最大半径
      let deviationR1 = 4000, deviationR2 = 4000  // 每次增加的半径
      const changeR1 = () => {
        minR1 += deviationR1
        if (minR1 >= maxR1) {
          minR1 = 4000
        }
        return minR1
      }
      const changeR2 = () => {
        minR2 += deviationR2
        if (minR2 >= maxR2) {
          minR2 = 4000
        }
        return minR2
      }
      this.circularDiffusion = this.entities.add({
        position: Cesium.Cartesian3.fromDegrees(105, 35),
        ellipse: {
          semiMinorAxis: new Cesium.CallbackProperty(changeR1, false),
          semiMajorAxis: new Cesium.CallbackProperty(changeR2, false),
          outline: true,
          outlineColor: new Cesium.CallbackProperty(() => {
            let x = 1 - minR1 / maxR1
            return Cesium.Color.RED.withAlpha(x)
          }, false),
          material: new Cesium.ImageMaterialProperty({
            image: '扩散圈.png',
            repeat: new Cesium.Cartesian2(1.0, 1.0),
            transparent: true,
            color: new Cesium.CallbackProperty(function () {
              var alp = 1
              alp = 1 - minR1 / maxR1
              return Cesium.Color.WHITESMOKE.withAlpha(alp)
            }, false)
          })
        }
      })
      this.trackedEntity = this.circularDiffusion
    }
  }
  // 28，添加飞线效果
  addFlyingLine(flyingLineChecked) {
    if (flyingLineChecked) {
      this.flyLine.values.forEach(entity => {
        this.entities.remove(entity)
      })
      this.flyLine.removeAll()
      this.reset()
    } else {
      // 设置矩形区域
      let bbox = [113.2691, 23.014, 118.3691, 30.159]
      // 创建随机点
      let points = turf.randomPoint(1000, {
        bbox: bbox,
      })
      // 通过生成的随机点生成线
      let features = points.features
      features.forEach((item) => {
        // 获取点的经纬度
        let point = item.geometry.coordinates
        // 根据点设置起始位置
        let start = Cesium.Cartesian3.fromDegrees(point[0], point[1], 0)
        // 根据点设置结束位置
        let end = Cesium.Cartesian3.fromDegrees(
          point[0],
          point[1],
          1000 + Math.random() * 20000
        )
        //   创建自定义线材质
        let polylineTrailMaterialProperty = new PolylineTrailMaterialProperty()
        //   创建线
        this.flyLine.add(this.entities.add({
          polyline: {
            positions: [start, end],
            width: 2,
            material: polylineTrailMaterialProperty,
          },
        }))
      })
      this.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(
          // 经度
          115.3301,
          // 纬度
          25.0991,
          // 高度
          1500
        ),
        orientation: {
          heading: Cesium.Math.toRadians(-45),
          pitch: Cesium.Math.toRadians(-10),
          roll: 0,
        },
        duration: 2,
      })
    }
  }
  // 29，添加流动水图
  addFlowingWater(flowingWaterChecked) {
    if (flowingWaterChecked) {
      this.scene.primitives.remove(this.flowingWater)
      this.flowingWater = null
      this.reset()
    } else {
      this.flowingWater = this.scene.primitives.add(new Cesium.Primitive({
        geometryInstances: new Cesium.GeometryInstance({
          geometry: new Cesium.PolygonGeometry({
            polygonHierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray([
              108, 30,
              115, 30,
              115, 35,
              108, 35
            ])),
            attributes: {
              color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
            }
          })
        }),
        appearance: new Cesium.EllipsoidSurfaceAppearance({
          aboveGround: false,
          material: new Cesium.Material({
            fabric: {
              type: 'Water',
              uniforms: {
                normalMap: 'waterNormals.jpg',
                frequency: 10000.0,
                animationSpeed: 0.01,
                amplitude: 1.0
              }
            }
          })
        })
      }))
      this.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(110, 33, 3000)
      })
    }
  }
  // 30，添加火焰粒子
  addFirePartices(fireParticesChecked) {
    if (fireParticesChecked) {
      this.scene.primitives.remove(this.firePartices)
      this.firePartices = null
      this.entities.remove(this.fireEntity)
      this.fireEntity = null
      this.reset()
    } else {
      const computeEmitterModelMatrix = () => {
        let hpr = Cesium.HeadingPitchRoll.fromDegrees(0.0, 0.0, 0.0)
        let trs = new Cesium.TranslationRotationScale()
        trs.translation = Cesium.Cartesian3.fromElements(
          -4.0,
          0.0,
          1.4,
        )
        trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr)

        return Cesium.Matrix4.fromTranslationRotationScale(trs)
      }
      this.fireEntity = this.entities.add({
        name: 'box',
        position: Cesium.Cartesian3.fromDegrees(113.3191, 33.109, 250),
        box: {
          dimensions: new Cesium.Cartesian3(100.0, 100.0, 500),
          material: Cesium.Color.RED.withAlpha(0.3),
        },
      })
      this.firePartices = this.scene.primitives.add(new Cesium.ParticleSystem({
        image: prefix + '/images/fire.png',
        imageSize: new Cesium.Cartesian2(20, 20),
        startColor: Cesium.Color.RED.withAlpha(0.7),
        endColor: Cesium.Color.YELLOW,
        startScale: 1.0,
        endScale: 4.0,
        minimumParticleLife: 1.2,
        maximumParticleLife: 1.2,
        speed: 5.0,
        minimumSpeed: 1.0,
        maximumSpeed: 4.0,
        emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(250, 250, 800)),
        emissionRate: 5.0,
        emitterModelMatrix: computeEmitterModelMatrix(),
        modelMatrix: this.fireEntity.computeModelMatrix(this.clock.currentTime, new Cesium.Matrix4()),
        lifetime: 16.0,
        bursts: [
          new Cesium.ParticleBurst({
            time: 5.0,
            minimum: 10,
            maximum: 100,
          }),
          new Cesium.ParticleBurst({
            time: 10.0,
            minimum: 50,
            maximum: 100,
          }),
          new Cesium.ParticleBurst({
            time: 15.0,
            minimum: 200,
            maximum: 300,
          }),
        ],
      }))
      this.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(113.3191, 33.109, 3000),
      })
    }
  }
  // 31，添加大雾粒子
  addFogParticles(fogParticlesChecked) {
    if (fogParticlesChecked) {
      if (this.fogParticles) {
        this.fogParticles.destroy()
        this.fogParticles = null
      }
      this.reset()
    } else {
      this.fogParticles = new FogEffect(this, {
        visibility: 0.1,
        color: new Cesium.Color.fromCssColorString('white')
      })
    }
  }
  // 32，添加下雨效果
  addRainEffect(rainEffectChecked) {
    if (rainEffectChecked) {
      if (this.rainEffect) {
        this.rainRender = null
        this.scene.primitives.remove(this.rainEffect)
        this.rainEffect = null
      }
      this.reset()
    } else {
      const rainUpdate = function (particle, dt) {
        let rainGravityScratch = Cesium.Cartesian3.normalize(particle.position, new Cesium.Cartesian3())
        rainGravityScratch = Cesium.Cartesian3.multiplyByScalar(
          rainGravityScratch,
          -1050.0,
          rainGravityScratch
        )
        particle.position = Cesium.Cartesian3.add(
          particle.position,
          new Cesium.Cartesian3(-50.0, 100.0, 0.0),
          particle.position
        )
      }
      this.rainEffect = this.scene.primitives.add(
        new Cesium.ParticleSystem({
          modelMatrix: new Cesium.Matrix4.fromTranslation(
            this.scene.camera.position
          ),
          speed: 1.0,
          lifetime: 15.0,
          emitter: new Cesium.SphereEmitter(100000),
          startScale: 1.0,
          endScale: 0.0,
          image: prefix + "/images/circular_particle.png",
          emissionRate: 9000.0,
          startColor: new Cesium.Color(0.27, 0.5, 0.7, 0.3),
          endColor: new Cesium.Color(0.27, 0.5, 0.7, 0.98),
          imageSize: new Cesium.Cartesian2(
            15,
            30
          ),
          updateCallback: rainUpdate,
        })
      );
      this.scene.skyAtmosphere.hueShift = -0.97;
      this.scene.skyAtmosphere.saturationShift = 0.25;
      this.scene.skyAtmosphere.brightnessShift = -0.4;
      this.scene.fog.density = 0.00025;
      this.scene.fog.minimumBrightness = 0.01;
      // 更新函数
      this.rainRender = () => {
        // 获取当前视图的中心位置
        var center = this.scene.camera.position;
        if (this.rainEffect) {
          // 更新粒子系统位置
          this.rainEffect.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center)
          // 请求下一帧更新
          requestAnimationFrame(this.rainRender)
        }
      }
      // 启动更新循环
      this.rainRender()
    }
  }
  // 33，添加雪花效果
  addSnowFlakeEffect(snowFlakeEffectChecked) {
    if (snowFlakeEffectChecked) {
      this.snowRender = null
      this.scene.primitives.remove(this.snowFlakeEffect)
      this.snowFlakeEffect = null
      this.reset()
    } else {
      const snowUpdate = function (particle, dt) {
        let snowGravityScratch = Cesium.Cartesian3.normalize(particle.position, new Cesium.Cartesian3())
        Cesium.Cartesian3.multiplyByScalar(
          snowGravityScratch,
          -9.8 * dt,
          snowGravityScratch
        );

        particle.velocity = Cesium.Cartesian3.add(
          particle.velocity,
          new Cesium.Cartesian3(-50.0, 100.0, 0.0),
          particle.velocity
        );
      }
      this.snowFlakeEffect = this.scene.primitives.add(
        new Cesium.ParticleSystem({
          modelMatrix: new Cesium.Matrix4.fromTranslation(
            this.scene.camera.position
          ),
          minimumSpeed: 1.0,
          maximumSpeed: 10.0,
          lifetime: 15.0,
          emitter: new Cesium.SphereEmitter(100000),
          startScale: 0.5,
          endScale: 1.0,
          image: prefix + "/images/snowflake_particle.png",
          emissionRate: 7000.0,
          startColor: Cesium.Color.WHITE.withAlpha(0.0),
          endColor: Cesium.Color.WHITE.withAlpha(1.0),
          minimumImageSize: new Cesium.Cartesian2(12, 12),
          maximumImageSize: new Cesium.Cartesian2(24, 24),
          updateCallback: snowUpdate,
        })
      )
      this.scene.skyAtmosphere.hueShift = -0.8
      this.scene.skyAtmosphere.saturationShift = -0.7
      this.scene.skyAtmosphere.brightnessShift = -0.33
      this.scene.fog.density = 0.001
      this.scene.fog.minimumBrightness = 0.8
      // 更新函数
      this.snowRender = () => {
        // 获取当前视图的中心位置
        var center = this.scene.camera.position
        if (this.snowFlakeEffect) {
          // 更新粒子系统位置
          this.snowFlakeEffect.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center)
          // 请求下一帧更新
          requestAnimationFrame(this.snowRender)
        }
      }
      // 启动更新循环
      this.snowRender()
    }
  }
  // 34，添加测量距离工具
  addMeasureDistance(measureDistanceChecked) {
    if (measureDistanceChecked) {
      if (this.measureDistance) {
        this.measureDistance.clear()
        this.measureDistance = null
      }
      this.reset()
    } else {
      this.measureDistance = new MeasureDistance(this)
      this.measureDistance.activate()
    }
  }
  // 35，添加测量面积工具
  addMeasureArea(measureAreaChecked) {
    if (measureAreaChecked) {
      if (this.measureArea) {
        this.measureArea.clear()
        this.measureArea = null
      }
      this.reset()
    } else {
      this.measureArea = new MeasureArea(this)
      this.measureArea.activate()
    }
  }
  // 36，添加测量高程工具
  addMeasureHeight(measureHeightChecked) {
    if (measureHeightChecked) {
      if (this.measureHeight) {
        this.measureHeight.clear()
        this.measureHeight = null
      }
      this.reset()
    } else {
      this.measureHeight = new MeasureHeight(this)
      this.measureHeight.activate()
    }
  }
  // 37，添加广州塔
  addGuangzhouTower(guangzhouTowerChecked) {
    if (guangzhouTowerChecked) {
      this.scene.primitives.remove(this.osmBuildings)
      this.flyLine.values.forEach(item => {
        this.entities.remove(item)
      })
      this.flyLine.removeAll()
      this.osmBuildings = null
      this.reset()
    } else {
      this.osmBuildings = Cesium.createOsmBuildings()
      this.scene.primitives.add(this.osmBuildings)
      this.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(
          // 经度
          113.3301,
          // 纬度
          23.0991,
          // 高度
          1500
        ),
        orientation: {
          heading: Cesium.Math.toRadians(-45),
          pitch: Cesium.Math.toRadians(-30),
          roll: 0,
        },
        duration: 2,
      })
      this.osmBuildings.tileVisible.addEventListener(tile => {
        const cesium3DTileCon = tile.content
        const featuresLength = cesium3DTileCon.featuresLength
        for (let i = 0; i < featuresLength; i++) {
          const model = cesium3DTileCon.getFeature(i).content._model

          // 修改模型的片元着色器
          const fragmentShaderSource =
            (model._rendererResources.sourceShaders[1] = `
                  varying vec3 v_positionEC;
    
                  void main()
                  {
                      czm_materialInput materialInput;
                      // 获取模型position信息
                      vec4 position = czm_inverseModelView * vec4(v_positionEC, 1.0);
                      //   根据高度来设置渐变颜色
                      float  strength = position.z/200.0;
                      gl_FragColor = vec4(strength,0.3*strength,strength, 1.0);
    
                      //   动态光环
                      //   czm_frameNumber获取当前帧数
                      //   fract(x),返回x的小数部分
                      float time  = fract(czm_frameNumber/(60.0*10.0));
                    //   实现往返的操作
                       time = abs(time-0.5)*2.0;
                    // time = sin(time);
                    // clamp(x, min, max)，返回x在min和max之间的最小值
                    float diff = abs(clamp(position.z/500.0, 0.0, 1.0) - time) ;
                    // step(edge, x)，如果x大于等于edge，返回1，否则返回0
                    diff = step(0.01, diff);
                    gl_FragColor.rgb += vec3(0.5)*(1.0-diff);
                  }
    
              `)

          // 片元着色器已经修改，需要更新
          model._shouldRegenerateShaders = true
        }
      })
      // 设置矩形区域
      let bbox = [113.2691, 23.014, 113.3691, 23.159]
      // 创建随机点
      let points = turf.randomPoint(300, {
        bbox: bbox,
      })
      // 通过生成的随机点生成线
      let features = points.features
      features.forEach((item) => {
        // 获取点的经纬度
        let point = item.geometry.coordinates
        // 根据点设置起始位置
        let start = Cesium.Cartesian3.fromDegrees(point[0], point[1], 0)
        // 根据点设置结束位置
        let end = Cesium.Cartesian3.fromDegrees(
          point[0],
          point[1],
          200 + Math.random() * 3000
        )
        //   创建自定义线材质
        let polylineTrailMaterialProperty = new PolylineTrailMaterialProperty()
        //   创建线
        this.flyLine.add(this.entities.add({
          polyline: {
            positions: [start, end],
            width: 2,
            material: polylineTrailMaterialProperty,
          },
        }))
      })
    }
  }
}